package com.boot2.core.utils;

import com.boot2.core.exception.BusinessException;
import lombok.extern.apachecommons.CommonsLog;
import okhttp3.*;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * http工具类，底层为okhttp,用来取代apache的httpClient
 *
 * @description:
 * @CreateDate:2018年3月29日 下午2:55:26
 * @Author:zhangweilin
 */
@SuppressWarnings("all")
@CommonsLog
public class HttpsClient extends AbstractHttpsClient {

    /**
     * 发起get请求
     *
     * @param url
     * @param params 参数
     * @return
     */
    public static String get(String url, Map<String, Object> params) {
        log.info("请求url: " + url + ",请求参数:" + (params == null ? "" : params.toString()));
        try {
            // 创建请求对象
            Call call = getGetCall(url, params);
            Response response = call.execute();
            String result = response.body().string();
            return result;
        } catch (IOException e) {
            e.printStackTrace();
            throw new BusinessException("请求失败，url: " + url, e);
        }
    }

    /**
     * 异步 发起get请求
     *
     * @param url
     * @param params
     * @param abstractCallback
     */
    public static void getAsync(String url, Map<String, Object> params, AbstractCallback abstractCallback) {
        log.info("请求url: " + url + ",请求参数:" + (params == null ? "" : params.toString()));
        // 创建请求对象
        Call call = getGetCall(url, params);
        call.enqueue(abstractCallback);
    }


    /**
     * 发起get请求
     *
     * @param url
     * @param headerMap header头
     * @param params    请求参数
     * @return
     */
    public static String getWithHeader(String url, Map<String, String> headerMap, Map<String, Object> params) {
        log.info("请求url: " + url + ",请求参数:" + (params == null ? "" : params.toString()));
        try {
            // 创建请求对象
            Call call = getGetCall(url, headerMap, params);
            Response response = call.execute();
            String result = response.body().string();
            return result;
        } catch (IOException e) {
            e.printStackTrace();
            throw new BusinessException("请求失败,url: " + url);
        }
    }

    /**
     * 发起get请求
     *
     * @param url
     * @param headerMap header头
     * @param params    请求参数
     * @return
     */
    public static void getWithHeaderAsync(String url, Map<String, String> headerMap, Map<String, Object> params, AbstractCallback abstractCallback) {
        log.info("请求url: " + url + ",请求参数:" + (params == null ? "" : params.toString()));
        Call call = getGetCall(url, headerMap, params);
        call.enqueue(abstractCallback);
    }

    /**
     * 发起get请求
     *
     * @param url
     * @param params 请求参数
     * @return 返回一个map, 其中key=result时，value为请求返回文本，key=headers，value为头部集合
     */
    public static Map<String, Object> getWithReturnHeader(String url, Map<String, Object> params) {
        log.info("请求url: " + url + ",请求参数:" + params.toString());
        // 创建请求对象
        Call call = getGetCall(url, params);
        try {
            Response response = call.execute();
            String result = response.body().string();
            Headers headers = response.headers();
            Map<String, Object> resultMap = new HashMap<String, Object>(2);
            resultMap.put("result", result);
            resultMap.put("headers", headers);
            return resultMap;

        } catch (IOException e) {
            e.printStackTrace();
            throw new BusinessException("请求失败,url: " + url);
        }
    }

    /**
     * 发起get请求
     *
     * @param url
     * @param headerMap 请求的header
     * @param params    请求参数
     * @return 返回一个map, 其中key=result时，value为请求返回文本，key=headers，value为头部集合
     */
    public static Map<String, Object> getWithHeaderAndReturnHeader(String url, Map<String, String> headerMap, Map<String, Object> params) {
        log.info("请求url: " + url + ",请求参数:" + params.toString());
        // 创建请求对象
        Call call = getGetCall(url, headerMap, params);
        try {
            Response response = call.execute();
            String result = response.body().string();
            Headers headers = response.headers();
            Map<String, Object> resultMap = new HashMap<String, Object>(2);
            resultMap.put("result", result);
            resultMap.put("headers", headers);
            return resultMap;

        } catch (IOException e) {
            e.printStackTrace();
            throw new BusinessException("请求失败,url: " + url);
        }
    }


    /**
     * 发起post请求
     *
     * @param url
     * @param reqMap 请求参数
     * @return
     */
    public static String postForm(String url, Map<String, Object> reqMap) {
        if (url.startsWith("https://")) {
            return posts(url, reqMap, MEDIA_TYPE_FORM);
        }
        try {
            RequestBody body = createRequestBody(MEDIA_TYPE_FORM, reqMap);
            return sendReq(url, body);
        } catch (IOException e) {
            e.printStackTrace();
            throw new BusinessException("请求失败,url: " + url);
        }
    }

    /**
     * 异步 发起post请求
     *
     * @param url
     * @param reqMap 请求参数
     * @return
     */
    public static void postFormAsync(String url, Map<String, Object> reqMap, AbstractCallback abstractCallback) {
        if (url.startsWith("https://")) {
            postsAsync(url, reqMap, MEDIA_TYPE_FORM, abstractCallback);
            return;
        }
        RequestBody body = createRequestBody(MEDIA_TYPE_FORM, reqMap);
        sendReqAsync(url, body, abstractCallback);
    }

    /**
     * 发起post请求
     *
     * @param url
     * @param headerMap header参数
     * @param reqMap    请求参数
     * @return
     */
    public static String postFormWithHeader(String url, Map<String, String> headerMap, Map<String, Object> reqMap) {
        if (url.startsWith("https://")) {
            return posts(url, reqMap, MEDIA_TYPE_FORM);
        }

        try {
            RequestBody body = createRequestBody(MEDIA_TYPE_FORM, reqMap);
            return sendReq(url, headerMap, body);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 异步 发起post请求
     *
     * @param url
     * @param headerMap header参数
     * @param reqMap    请求参数
     * @return
     */
    public static void postFormWithHeaderAsync(String url, Map<String, String> headerMap, Map<String, Object> reqMap, AbstractCallback abstractCallback) {
        if (url.startsWith("https://")) {
            postsAsync(url, reqMap, MEDIA_TYPE_FORM, abstractCallback);
            return;
        }
        RequestBody body = createRequestBody(MEDIA_TYPE_FORM, reqMap);
        sendReqAsync(url, headerMap, body, abstractCallback);
    }

    /**
     * 发起post请求
     *
     * @param url
     * @param reqMap 请求参数
     * @return 返回一个map, 其中key=result时，value为请求返回文本，key=headers，value为头部集合
     */
    public static Map<String, Object> postFormWithReturnHeader(String url, Map<String, Object> reqMap) {
        if (url.startsWith("https://")) {
            return postsWithReturnHeader(url, reqMap, MEDIA_TYPE_FORM);
        }
        RequestBody body = createRequestBody(MEDIA_TYPE_FORM, reqMap);
        return sendReqWithReturnHeader(url, body);
    }

    /**
     * 发起post请求
     *
     * @param url
     * @param headerMap 请求header参数
     * @param reqMap    请求参数
     * @return 返回一个map, 其中key=result时，value为请求返回文本，key=headers，value为头部集合
     */
    public static Map<String, Object> postFormWithHeaderAndReturnHeader(String url, Map<String, String> headerMap, Map<String, Object> reqMap) {
        if (url.startsWith("https://")) {
            return postsWithReturnHeader(url, reqMap, MEDIA_TYPE_FORM);
        }
        RequestBody body = createRequestBody(MEDIA_TYPE_FORM, reqMap);
        return sendReqWithReturnHeader(url, headerMap, body);
    }

    /**
     * 发起json请求
     *
     * @param url
     * @param json 请求参数
     * @return
     */
    public static String postJson(String url, String json) {
        if (url.startsWith("https://")) {
            return postsJson(url, json, MEDIA_TYPE_JSON);
        }
        try {
            RequestBody body = createJsonRequestBodyWithParamMap(MEDIA_TYPE_JSON, json, null);
            return sendReq(url, body);
        } catch (IOException e) {
            e.printStackTrace();
            throw new BusinessException("请求失败,url: " + url, e);
        }
    }

    /**
     * 异步 发起json请求
     *
     * @param url
     * @param json 请求参数
     * @return
     */
    public static void postJsonAsync(String url, String json, AbstractCallback abstractCallback) {
        if (url.startsWith("https://")) {
            postsJsonAsync(url, json, MEDIA_TYPE_JSON, abstractCallback);
            return;
        }
        RequestBody body = createJsonRequestBodyWithParamMap(MEDIA_TYPE_JSON, json, null);
        sendReqAsync(url, body, abstractCallback);
    }

    /**
     * 发起json请求
     *
     * @param url
     * @param json     请求参数
     * @param paramMap 请求参数
     * @return
     */
    public static String postJsonAndParamMap(String url, String json, Map<String, String> paramMap) {
        url = concatParams(url, paramMap);
        if (url.startsWith("https://")) {
            return postsJsonAndHeaderAndParamMapWithHeader(url, json, MEDIA_TYPE_JSON, paramMap, null);
        }

        try {
            RequestBody body = createJsonRequestBodyWithParamMap(MEDIA_TYPE_JSON, json, paramMap);
            return sendReq(url, body);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 异步发起json请求
     *
     * @param url
     * @param json     请求参数
     * @param paramMap 请求参数
     * @return
     */
    public static void postJsonAndParamMapAsync(String url, String json, Map<String, String> paramMap, AbstractCallback abstractCallback) {
        url = concatParams(url, paramMap);
        if (url.startsWith("https://")) {
            postsJsonAndHeaderAndParamMapWithHeaderAsync(url, json, MEDIA_TYPE_JSON, paramMap, null, abstractCallback);
            return;
        }
        RequestBody body = createJsonRequestBodyWithParamMap(MEDIA_TYPE_JSON, json, paramMap);
        sendReqAsync(url, body, abstractCallback);
    }

    /**
     * 发起json请求
     *
     * @param url
     * @param headerMap 请求header参数
     * @param json      请求参数
     * @return
     */
    public static String postJsonWithHeader(String url, Map<String, String> headerMap, String json) {
        if (url.startsWith("https://")) {
            return postsJsonAndHeaderAndParamMapWithHeader(url, json, MEDIA_TYPE_JSON, null, headerMap);
        }

        try {
            RequestBody body = createJsonRequestBodyWithParamMap(MEDIA_TYPE_JSON, json, null);
            return sendReq(url, headerMap, body);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 异步 发起json请求
     *
     * @param url
     * @param headerMap 请求header参数
     * @param json      请求参数
     * @return
     */
    public static void postJsonWithHeaderAsync(String url, Map<String, String> headerMap, String json, AbstractCallback abstractCallback) {
        if (url.startsWith("https://")) {
            postsJsonAndHeaderAndParamMapWithHeaderAsync(url, json, MEDIA_TYPE_JSON, null, headerMap, abstractCallback);
            return;
        }
        RequestBody body = createJsonRequestBodyWithParamMap(MEDIA_TYPE_JSON, json, null);
        sendReqAsync(url, headerMap, body, abstractCallback);
    }

    /**
     * 发起json请求
     *
     * @param url
     * @param headerMap 请求header参数
     * @param json      请求参数
     * @return
     */
    public static String postJsonAndParamMapWithHeader(String url, Map<String, String> headerMap, String json, Map<String, String> paramMap) {
        url = concatParams(url, paramMap);
        if (url.startsWith("https://")) {
            return postsJsonAndHeaderAndParamMapWithHeader(url, json, MEDIA_TYPE_JSON, paramMap, headerMap);
        }
        try {
            RequestBody body = createJsonRequestBodyWithParamMap(MEDIA_TYPE_JSON, json, paramMap);
            return sendReq(url, headerMap, body);
        } catch (IOException e) {
            e.printStackTrace();
            throw new BusinessException("请求失败,url: " + url, e);
        }
    }

    /**
     * 异步 发起json请求
     *
     * @param url
     * @param headerMap 请求header参数
     * @param json      请求参数
     * @return
     */
    public static void postJsonAndParamMapWithHeaderAsync(String url, Map<String, String> headerMap, String json, Map<String, String> paramMap, AbstractCallback abstractCallback) {
        url = concatParams(url, paramMap);
        if (url.startsWith("https://")) {
            postsJsonAndHeaderAndParamMapWithHeaderAsync(url, json, MEDIA_TYPE_JSON, paramMap, headerMap, abstractCallback);
            return;
        }
        RequestBody body = createJsonRequestBodyWithParamMap(MEDIA_TYPE_JSON, json, paramMap);
        sendReqAsync(url, headerMap, body, abstractCallback);
    }

    /**
     * 发起json请求
     *
     * @param url
     * @param json 请求参数
     * @return 返回一个map, 其中key=result时，value为请求返回文本，key=headers，value为头部集合
     */
    public static Map<String, Object> postJsonWithReturnHeader(String url, String json) {
        if (url.startsWith("https://")) {
            return postsJsonAndHeaderAndParamMapWithReturnHeader(url, json, MEDIA_TYPE_JSON, null, null);
        }
        RequestBody body = createJsonRequestBodyWithParamMap(MEDIA_TYPE_JSON, json, null);
        return sendReqWithReturnHeader(url, body);
    }

    /**
     * 发起json请求
     *
     * @param url
     * @param json 请求参数
     * @return 返回一个map, 其中key=result时，value为请求返回文本，key=headers，value为头部集合
     */
    public static Map<String, Object> postJsonAndParamMapWithReturnHeader(String url, String json, Map<String, String> paramMap) {
        url = concatParams(url, paramMap);
        if (url.startsWith("https://")) {
            return postsJsonAndHeaderAndParamMapWithReturnHeader(url, json, MEDIA_TYPE_JSON, paramMap, null);
        }
        RequestBody body = createJsonRequestBodyWithParamMap(MEDIA_TYPE_JSON, json, paramMap);
        return sendReqWithReturnHeader(url, body);
    }


    /**
     * 发起json请求
     *
     * @param url
     * @param headerMap 请求header参数
     * @param reqMap    请求参数
     * @return 返回一个map, 其中key=result时，value为请求返回文本，key=headers，value为头部集合
     */

    public static Map<String, Object> postJsonWithHeaderAndReturnHeader(String url, Map<String, String> headerMap, String json) {
        if (url.startsWith("https://")) {
            return postsJsonAndHeaderAndParamMapWithReturnHeader(url, json, MEDIA_TYPE_JSON, null, headerMap);
        }
        RequestBody body = createJsonRequestBodyWithParamMap(MEDIA_TYPE_JSON, json, null);
        return sendReqWithReturnHeader(url, headerMap, body);
    }


    /**
     * 发起json请求
     *
     * @param url
     * @param headerMap 请求header参数
     * @param reqMap    请求参数
     * @return 返回一个map, 其中key=result时，value为请求返回文本，key=headers，value为头部集合
     */

    public static Map<String, Object> postJsonAndParamMapWithHeaderAndReturnHeader(String url, Map<String, String> headerMap, String json,
                                                                                   Map<String, String> paramMap) {
        url = concatParams(url, paramMap);
        if (url.startsWith("https://")) {
            return postsJsonAndHeaderAndParamMapWithReturnHeader(url, json, MEDIA_TYPE_JSON, paramMap, headerMap);
        }
        RequestBody body = createJsonRequestBodyWithParamMap(MEDIA_TYPE_JSON, json, paramMap);
        return sendReqWithReturnHeader(url, headerMap, body);
    }

    /**
     * @description 创建支持https请求 @Author liangjl @Date 2018年2月9日 下午3:25:47 @param
     * url @param reqMap @param contentType 参数 @return void
     * 返回类型 @throws
     */
    private static Map<String, Object> postsJsonAndHeaderAndParamMapWithReturnHeader(String url, String json, String contentType, Map<String, String> pararmMap,
                                                                                     Map<String, String> headerMap) {
        /** 忽略SSL协议证书 */
        final Call call = getPostsJsonCall(url, json, contentType, pararmMap, headerMap);
        Headers headers = null;
        try {
            Response response = call.execute();
            String result = response.body().string();
            headers = response.headers();
            Map<String, Object> resultMap = new HashMap<String, Object>(2);
            resultMap.put("result", result);
            resultMap.put("headers", headers);
            return resultMap;
        } catch (IOException e) {
            e.printStackTrace();
            throw new BusinessException("请求失败,url: " + url, e);
        }
    }

    /**
     * @description 创建支持https请求 @Author liangjl @Date 2018年2月9日 下午3:25:47 @param
     * url @param reqMap @param contentType 参数 @return void
     * 返回类型 @throws
     */
    private static void postsJsonAndHeaderAndParamMapAsync(String url, String json, String contentType, Map<String, String> pararmMap,
                                                           Map<String, String> headerMap, AbstractCallback abstractCallback) {
        /** 忽略SSL协议证书 */
        final Call call = getPostsJsonCall(url, json, contentType, pararmMap, headerMap);
        Headers headers = null;
        call.enqueue(abstractCallback);
    }


    /**
     * @description 创建支持https请求 @Author liangjl @Date 2018年2月9日 下午3:25:47 @param
     * url @param reqMap @param contentType 参数 @return void
     * 返回类型 @throws
     */
    private static String posts(String url, Map<String, Object> reqMap, String contentType) {
        /** 忽略SSL协议证书 */
        OkHttpClient build = getHttpsInstance();
        final RequestBody body = createRequestBody(contentType, reqMap);
        final Request request = new Request.Builder().url(url).post(body).build();
        final Call call = build.newCall(request);
        try {
            Response response = call.execute();
            return response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
            throw new BusinessException("请求失败,url: " + url, e);
        }
    }

    /**
     * @description 创建支持https请求 @Author liangjl @Date 2018年2月9日 下午3:25:47 @param
     * url @param reqMap @param contentType 参数 @return void
     * 返回类型 @throws
     */
    private static void postsAsync(String url, Map<String, Object> reqMap, String contentType, AbstractCallback abstractCallback) {
        /** 忽略SSL协议证书 */
        OkHttpClient build = getHttpsInstance();
        final RequestBody body = createRequestBody(contentType, reqMap);
        final Request request = new Request.Builder().url(url).post(body).build();
        final Call call = build.newCall(request);
        call.enqueue(abstractCallback);
    }

    /**
     * @description 创建支持https请求 @Author liangjl @Date 2018年2月9日 下午3:25:47 @param
     * url @param reqMap @param contentType 参数 @return void
     * 返回类型 @throws
     */
    private static String postsJson(String url, String json, String contentType) {
        /** 忽略SSL协议证书 */
        OkHttpClient build = getHttpsInstance();
        final RequestBody body = createJsonRequestBodyWithParamMap(contentType, json, null);
        final Request request = new Request.Builder().url(url).post(body).build();
        final Call call = build.newCall(request);
        try {
            Response response = call.execute();
            return response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
            throw new BusinessException("请求失败,url: " + url, e);
        }
    }

    /**
     * @description 创建支持https请求 @Author liangjl @Date 2018年2月9日 下午3:25:47 @param
     * url @param reqMap @param contentType 参数 @return void
     * 返回类型 @throws
     */
    private static void postsJsonAsync(String url, String json, String contentType, AbstractCallback abstractCallback) {
        /** 忽略SSL协议证书 */
        OkHttpClient build = getHttpsInstance();
        final RequestBody body = createJsonRequestBodyWithParamMap(contentType, json, null);
        final Request request = new Request.Builder().url(url).post(body).build();
        final Call call = build.newCall(request);
        call.enqueue(abstractCallback);
    }

    /**
     * @description 创建支持https请求 @Author liangjl @Date 2018年2月9日 下午3:25:47 @param
     * url @param reqMap @param contentType 参数 @return void
     * 返回类型 @throws
     */
    private static String postsJsonAndHeaderAndParamMapWithHeader(String url, String json, String contentType, Map<String, String> pararmMap,
                                                                  Map<String, String> headerMap) {
        /** 忽略SSL协议证书 */
        final Call call = getPostsJsonCall(url, json, contentType, pararmMap, headerMap);
        try {
            Response response = call.execute();
            return response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
            throw new BusinessException("请求失败,url: " + url, e);
        }
    }

    /**
     * @description 创建支持https请求 @Author liangjl @Date 2018年2月9日 下午3:25:47 @param
     * url @param reqMap @param contentType 参数 @return void
     * 返回类型 @throws
     */
    private static void postsJsonAndHeaderAndParamMapWithHeaderAsync(String url, String json, String contentType, Map<String, String> pararmMap,
                                                                     Map<String, String> headerMap, AbstractCallback abstractCallback) {
        final Call call = getPostsJsonCall(url, json, contentType, pararmMap, headerMap);
        call.enqueue(abstractCallback);
    }


    /**
     * @description 创建支持https请求 @Author liangjl @Date 2018年2月9日 下午3:25:47 @param
     * url @param reqMap @param contentType 参数 @return void
     * 返回类型 @throws
     */
    private static Map<String, Object> postsWithReturnHeader(String url, Map<String, Object> reqMap, String contentType) {
        /** 忽略SSL协议证书 */
        OkHttpClient build = getHttpsInstance();
        final RequestBody body = createRequestBody(contentType, reqMap);
        final Request request = new Request.Builder().url(url).post(body).build();
        final Call call = build.newCall(request);
        try {
            Response response = call.execute();
            String result = response.body().string();
            Headers headers = response.headers();
            Map<String, Object> resultMap = new HashMap<String, Object>(2);
            resultMap.put("result", result);
            resultMap.put("headers", headers);
            return resultMap;
        } catch (IOException e) {
            e.printStackTrace();
            throw new BusinessException("请求失败,url: " + url, e);
        }
    }

    //==============以下为代理方式获取==========================

    /**
     * 发起get请求
     *
     * @param url
     * @param params 参数
     * @return
     */
    public static String proxyGet(String proxyHost, Integer proxyPort,String url, Map<String, Object> params) {
        log.info("请求url: " + url + ",请求参数:" + (params == null ? "" : params.toString()));
        try {
            // 创建请求对象
            Call call = getProxyGetCall(proxyHost,proxyPort,url, params);
            Response response = call.execute();
            String result = response.body().string();
            return result;
        } catch (IOException e) {
            e.printStackTrace();
            throw new BusinessException("请求失败，url: " + url, e);
        }
    }




    /**
     * 发起json请求
     *
     * @param url
     * @param json 请求参数
     * @return
     */
//    public static String postJson(String url, String json) {
//        return "";
//    }

}

//###############################以下为测试#########################
//class UnitTest {
//    public static void main(String[] args) {
////        testAsyncGet1();
//        testAsyncPostForm1();
//    }
//
//    private static void testAsyncPostForm1() {
//        for (final int[] i = new int[1]; i[0] < 300; i[0]++) {
//            Map<String, Object> paramMap = new HashMap<>();
//            paramMap.put("aaaa", "22233");
//            HttpsClient.postFormAsync("https://app.sz-zoomlight.com/web/v1/sys/showSjToken", paramMap, new HttpsClient.AbstractCallback() {
//                @Override
//                public void onResponse(String result) {
//                    System.out.println("result1" + i[0] + " = " + result);
//                }
//            });
//        }
//        System.out.println("请求完毕");
//    }
//
//    public static void testAsyncGet1() {
//        for (final int[] i = new int[1]; i[0] < 300; i[0]++) {
//            HttpsClient.getAsync("https://app.sz-zoomlight.com/web/v1/sys/showSjToken", null, new HttpsClient.AbstractCallback() {
//                @Override
//                public void onResponse(String result) {
//                    System.out.println("result1" + i[0] + " = " + result);
//                }
//            });
//        }
//        System.out.println("请求完毕");
//    }
//}